package com.schoolComments.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.schoolComments.dto.Result;
import com.schoolComments.dto.ScrollResult;
import com.schoolComments.dto.UserDTO;
import com.schoolComments.entity.Blog;
import com.schoolComments.entity.Follow;
import com.schoolComments.entity.User;
import com.schoolComments.mapper.BlogMapper;
import com.schoolComments.mapper.FollowMapper;
import com.schoolComments.mapper.UserMapper;
import com.schoolComments.service.IBlogService;
import com.schoolComments.utils.SystemConstants;
import com.schoolComments.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private BlogMapper blogMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private FollowMapper followMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryBlogByBlogId(Long id) {
        String key = "blog:likes:"+id;
        Long id1 = UserHolder.getUser().getId();
        Blog blog = blogMapper.queryBlogByBlogId(id);
        if (blog != null) {
            //查询是否点过赞 点过则将isLike字段设为true 前端则会高亮
            Double score = stringRedisTemplate.opsForZSet().score(key, id1+"");
            blog.setIsLike(score==null?false:true);
            return Result.ok(blog);
        }
        else{
            return Result.fail("没有相关博客");
        }
    }

    //点赞功能
    @Override
    public Result likeBlog(Long id) {
        //准备key
        String key = "blog:likes:"+id;
        //获取当前用户id
        Long userId = UserHolder.getUser().getId();
        //查redis中是否存在对应value
        Double score = stringRedisTemplate.opsForZSet().score(key, userId + "");
        if (score == null) {
            //不存在
            //更新db
            Integer count = blogMapper.updateLike(id, 1);
            //像redis的key中添加一条value
            if (count == 1) {
                stringRedisTemplate.opsForZSet().add(key, userId+"", System.currentTimeMillis());
            }
        }
        else{
            //存在
            //更新db
            Integer count = blogMapper.updateLike(id, -1);
            //从redis的key中删除一条value
            if (count == 1) {
                stringRedisTemplate.opsForZSet().remove(key, userId+"");
            }
        }
        return Result.ok();
    }

    //显示给博客点赞的用户们
    @Override
    public Result queryBlogLikes(Long id) {
        //准备key
        String key = "blog:likes:"+id;
        //在redis中查key相关的所有value
        Set<String> ids = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(ids == null || ids.isEmpty()){
            //没有数据
            //返回空集合
            return Result.ok(Collections.emptyList());
        }
        //有数据
        //根据这些id去db中查询相关用户 以userDTO形式返回(保护隐私)
        List<UserDTO> userDTOS = userMapper.queryUsersByIds(ids);
        return Result.ok(userDTOS);
    }

    @Override
    public Result queryBlogsById(Long id, Integer current) {
        PageHelper.startPage(current, SystemConstants.MAX_PAGE_SIZE);
        List<Blog> blogs = blogMapper.queryBlogsById(id);
        PageInfo<Blog> blogPageInfo = new PageInfo<>(blogs, SystemConstants.MAX_PAGE_SIZE);
        return Result.ok(blogPageInfo.getList());
    }

    @Override
    public Result queryMyBlog(Integer current) {
        //获取当前用户id
        Long id = UserHolder.getUser().getId();
        //开启分页插件
        PageHelper.startPage(current, SystemConstants.MAX_PAGE_SIZE);
        //执行查询操作
        List<Blog> blogs = blogMapper.queryMyBlog(id);
        //获取分页信息对象
        PageInfo<Blog> blogPageInfo = new PageInfo<>(blogs, SystemConstants.MAX_PAGE_SIZE);
        return Result.ok(blogPageInfo.getList());
    }


    @Override
    public Result queryHotBlog(Integer current) {
        //开启分页插件
        PageHelper.startPage(current, SystemConstants.MAX_PAGE_SIZE);
        //执行查询操作
        List<Blog> blogs = blogMapper.queryHotBlog();
        //获取分页信息对象
        PageInfo<Blog> blogPageInfo = new PageInfo<>(blogs, SystemConstants.MAX_PAGE_SIZE);
        List<Blog> blogList = blogPageInfo.getList();
        //像blog中添加用户的信息(写当前博客的用户的name 头像)
        blogList.forEach(blog ->{
            Long userId = blog.getUserId();
            User user = userMapper.queryUserById(userId);
            blog.setName(user.getNickName());
            blog.setIcon(user.getIcon());
        });
        return Result.ok(blogList);
    }

    public Result saveBlog(Blog blog){
        String keyPrefix = "receive:mailBox:";
        // 获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        // 保存探店博文
        blogMapper.insertOne(blog);
        //把当前博文写到所有粉丝的信箱(redis)中
        //redis中存的是博客的id 到时候粉丝可以直接根据redis中的id去拉取相应博客

        //找到当前登录用户的所有粉丝
        List<Follow> follows = followMapper.queryAllById(user.getId());
        Long blogId = blog.getId();
        //给粉丝信箱推送
        for (Follow follow : follows) {
            Long followUserId = follow.getFollowUserId();
            stringRedisTemplate.opsForZSet().add(keyPrefix+followUserId, blogId+"", System.currentTimeMillis());
        }
        // 返回id
        return Result.ok(blogId);
    }

    @Override
    public Result queryblogOfFollow(Long lastId, Integer offset) {
        //获取当前用户
        Long userId = UserHolder.getUser().getId();
        //查询收件箱
        String key = "receive:mailBox:"+userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
        .reverseRangeByScoreWithScores(key, 0, lastId, offset, 2);
        //非空判断
        if(typedTuples == null || typedTuples.isEmpty()){
            return Result.ok();
        }
        //解析数据
        ArrayList<Long> blogIds = new ArrayList<>(typedTuples.size());
        Long minTime = System.currentTimeMillis();
        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            Long blogId = Long.valueOf(typedTuple.getValue());
            long time = typedTuple.getScore().longValue();
            blogIds.add(blogId);
            minTime = Math.min(minTime, time);
        }
        //根据id查询blog
        Long[] ids = blogIds.toArray(new Long[blogIds.size()]);
        List<Blog> blogs = blogMapper.queryBlogsByIds(ids);
        offset = 1;
        //封装对象并返回
        ScrollResult result = new ScrollResult();
        result.setList(blogs);
        result.setOffset(offset);
        result.setMinTime(minTime);
        return Result.ok(result);
    }
}
